package com.example.springboottest.example.nio.netty.embed;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.embedded.EmbeddedChannel;

import java.nio.charset.StandardCharsets;

/**
 * 将 新 建 三 个 极 为 简 单 的 入 站 处 理 器 ， 在
 * ChannelInitializer 通道初始化处理器的 initChannel 方法中把它们加入到流水线中。三个入站处理器
 * 分别为：SimpleInHandlerA、SimpleInHandlerB、SimpleInHandlerC，添加的顺序为 A → B → C。
 * <p>
 * Netty 提供了 ByteBuf 来替代 Java NIO 的 ByteBuffer 缓冲区，以操纵内存缓冲区。
 * 与 Java NIO 的 ByteBuffer 相比，ByteBuf 的优势如下：
 * ⚫ Pooling (池化，这点减少了内存复制和 GC，提升了效率)
 * ⚫ 复合缓冲区类型，支持零复制
 * ⚫ 不需要调用 flip()方法去切换读/写模式
 * ⚫ 扩展性好，例如 StringBuffer
 * ⚫ 可以自定义缓冲区类型
 * ⚫ 读取和写入索引分开
 * ⚫ 方法的链式调用
 * ⚫ 可以进行引用计数，方便重复使用
 */
public class EmbeddedInBoundChannelTest {
    public static void main(String[] args) {
        ChannelInitializer i = new ChannelInitializer<EmbeddedChannel>() {
            protected void initChannel(EmbeddedChannel ch) {
                ch.pipeline().addLast(new SimpleInHandlerA());
                ch.pipeline().addLast(new SimpleInHandlerB());
                ch.pipeline().addLast(new SimpleInHandlerC());

                ch.pipeline().addLast(new EmbeddedOutBoundChannelTest.SimpleOutHandlerA());
                ch.pipeline().addLast(new EmbeddedOutBoundChannelTest.SimpleOutHandlerB());
                ch.pipeline().addLast(new EmbeddedOutBoundChannelTest.SimpleOutHandlerC());
            }
        };
        EmbeddedChannel channel = new EmbeddedChannel(i);
        ByteBuf buf = Unpooled.buffer();
        buf.writeInt(1);
        //向通道写一个入站报文（数据包）
        channel.writeInbound(buf);
        try {
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    static class SimpleInHandlerA extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws
                Exception {
            ByteBuf buf = ((ByteBuf) msg);
            int num = buf.readInt();
            System.out.println("入站处理器 A: 被回调 ，消息是" + num);
            super.channelRead(ctx, buf.writeInt(++num));

            //不调用基类的 channelRead, 终止流水线的执行
//            super.channelRead(ctx, msg);
        }
    }

    static class SimpleInHandlerB extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws
                Exception {
            ByteBuf buf = ((ByteBuf) msg);
            int num = buf.readInt();
            System.out.println("入站处理器 B: 被回调 ，消息是" + num);
            super.channelRead(ctx, buf.writeInt(++num));
        }
    }

    static class SimpleInHandlerC extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws
                Exception {
            ByteBuf buf = ((ByteBuf) msg);
            int num = buf.readInt();
            System.out.println("入站处理器 C: 被回调 ，消息是" + num);
            super.channelRead(ctx, buf.writeInt(++num));
            //出站发送消息
            ctx.channel().writeAndFlush(buf);
        }
    }


}
